<?php
//9.1 处理表单输入
if ($_SERVER['REQUEST_METHOD'] == 'GET') { ?>
    <form action="<?php echo htmlentities($_SERVER['SCRIPT_NAME']) ?>" method="post">
        <p>What is your first name?</p>
        <input type="text" name="first_name">
        <input type="submit" value="Say Hello">
    </form>
<?php } else {
    if (isset($_POST['first_name'])) {
        echo 'Hello, ' . $_POST['first_name'] . '!';
    }
}
?>

<?php
//9.2 验证表单输入：必填域
if (!filter_has_var(INPUT_POST, 'flavor')) {
    print "You must enter your favorite ice cream flavor.\n";
}

//严格表单验证
if (!(filter_has_var(INPUT_POST, 'flavor')) && (strlen(filter_input(INPUT_POST, 'flavor')) > 0)) {
    print "You must enter your favourite ice cream flavor.\n";
}

if (filter_has_var(INPUT_POST, 'color') && (strlen(filter_input(INPUT_POST, 'color', FILTER_SANITIZE_STRING)) <= 5)) {
    print "Color must be more than 5 characters.\n";
}

if (!(filter_has_var(INPUT_POST, 'choices') && filter_input(INPUT_POST, 'choices', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY))) {
    print "You must select some choices.\n";
}

//9.3 验证表单输入：数字
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
if ($age === false) {
    print "Submitted age is invalid.\n";
}

$price = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_FLOAT);
if ($price === false) {
    print "Submitted price is invalid.\n";
}

// 使用正则验证
if (isset($_POST['rating'])) {
    if (!preg_match('/^-?\d+$/', $_POST['rating'])) {
        print "Your rating must be an integer.\n";
    }
}

if (isset($_POST['temperature'])) {
    if (!preg_match('/^-?\d*\.?\d+$/', $_POST['temperature'])) {
        print "Your temperature must be a number.\n";
    }
}

//9.4 验证表单输入：email 地址
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === false) {
    print "Submitted email address is invalid.\n";
}

//9.5 下拉菜单
//生成菜单
$choices = ['Eggs', 'Toast', 'Coffee'];
echo "<br /><select name='food'>\n";
foreach ($choices as $choice) {
    echo "<option>$choice</option>\n";
}
echo "</select>";

if (isset($_POST['food'])) {
    if (!in_array($_POST['food'], $choices)) {
        echo "You must select a valid choice.\n";
    }
}

//9.6 验证表单输入：单选框
$defaults['food'] = 'toast';
$choices = ['eggs' => 'Eggs Benedict', 'toast' => 'Buttered Toast with Jam', 'coffee' => 'Piping Hot Coffee'];
foreach ($choices as $key => $choice) {
    echo "<br /><input type='radio' name='food' value='$key'";
    if ($key == $defaults['food']) {
        echo ' checked="checked"';
    }
    echo "/> $choice \n";
}

if (isset($_POST['food'])) {
    if (!array_key_exists($_POST['food'], $choices)) {
        echo "You must select a valid choice.\n";
    }
}

//9.7 验证表单输入：复选框
$value = 'yes';
echo "<br /><input type='checkbox' name='subscribe' value='yes' /> Subscribe?\n";

if (filter_has_var(INPUT_POST, 'subscribe')) {
    if ($_POST['subscribe'] == $value) {
        $subscribed = true;
    } else {
        $subscribed = false;
        print 'Invalid checkbox valud submitted.';
    }
} else {
    $subscribed = false;
}
if ($subscribed) {
    print "You are subscribed.\n";
} else {
    print "You are not subscribed.<br />";
}

//9.8 验证表单输入：日期和时间
$_POST['month'] = 5;
$_POST['day'] = 5;
$_POST['year'] = 2017;
if (!checkdate($_POST['month'], $_POST['day'], $_POST['year'])) {
    print "The date you entered doesn't exist! \n";
}

$expires = mktime(0, 0, 0, $_POST['month'], 1, $_POST['year']);
$lastMonth = strtotime('last month', $expires);
if (time() > $lastMonth) {
    print "Sorry, that credit card expires too soon.\n";
}

//9.9 验证表单输入：信用卡
function is_valid_credit_card($s)
{
    //删除非数字字符, 并反向
    $s = strrev(preg_replace('/[^\d]/', '', $s));
    $sum = 0;//计算验和
    for ($i = 0, $j = strlen($s); $i < $j; $i++) {
        if (($i % 2) == 0) {
            $val = $s[$i];
        } else {
            $val = $s[$i] * 2;
            if ($val > 9) {
                $val -= 9;
            }
        }
        $sum += $val;
    }
    //如果是10的倍数，卡号则是合法的
    return (($sum % 10) == 0);
}

$_POST['credit_card'] = '4111111111111111';
if (!is_valid_credit_card($_POST['credit_card'])) {
    print "Sorry, that card number is invalid.\n";
}

//9.10 防止跨站点脚本攻击
$_POST['comment'] = '<script>delete</script>';
print 'The comment was: ';
print htmlentities($_POST['comment']) . "\n";

?>
<?php //9.11 处理上传文件
if ($_SERVER['REQUEST_METHOD'] == 'GET') { ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['SCRIPT_NAME']) ?>" enctype="multipart/form-data">
        <input type="file" name="document">
        <input type="submit" value="Send File">
    </form>
<?php } else {
    if (isset($_FILES['document']) && $_FILES['document']['error'] == UPLOAD_ERR_OK) {
        $newPath = '/' . basename($_FILES['document']['name']);
        if (move_uploaded_file($_FILES['document']['tmp_name'], $newPath)) {
            print "File saved in $newPath \n";
        } else {
            print "Couldn't move file to $newPath \n";
        }
    } else {
        print "No valid file uploaded. \n";
    }
}
?>
<?php
//9.12 处理多页面表单
session_start();
if (($_SERVER['REQUEST_METHOD'] == 'GET') || (!isset($_POST['stage']))) {
    $stage = 1;
} else {
    $stage = (int)$_POST['stage'];
}
$stage = max($stage, 1);
$stage = min($stage, 3);

if ($stage > 1) {
    foreach ($_POST as $key => $value) {
        $_SESSION[$key] = $value;
    }
}
?>
    <form action="<?= htmlentities($_SERVER['SCRIPT_NAME']) ?>" method="post">
        Name: <input type="text" name="name"> <br>
        Age: <input type="text" name="age"> <br>
        <input type="hidden" name="stage" value="<?= $stage + 1 ?>">
        <input type="submit" value="Next">
    </form>

    <form action="<?= htmlentities($_SERVER['SCRIPT_NAME']) ?>" method="post">
        Favorite Color: <input type="text" name="color"> <br>
        Favorite Food: <input type="text" name="food"> <br>
        <input type="hidden" name="stage" value="<?= $stage + 1 ?>">
        <input type="submit" value="Done">
    </form>

    Hello <?= htmlentities($_SESSION['name']) ?>
    You are <?= htmlentities($_SESSION['age']) ?> years old.
    Your favorite color is <?= htmlentities($_SESSION['color']) ?>
    Your favorite food is <?= htmlentities($_SESSION['food']) ?> <br>

<?php
//9.13 重新显示表单并提供内敛错误消息
$flavors = ['Vanilla', 'Chocolate', ';Rhinoceros'];
$defaults = ['name' => '', 'age' => '', 'flavor' => []];
foreach ($flavors as $flavor) {
    $defaults['flavor'][$flavor] = '';
}
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    $errors = [];
} else {
    $errors = validate_form();
    if (count($errors)) {
        if (isset($_POST['name'])) {
            $defaults['name'] = $_POST['name'];
        }
        if (isset($_POST['age'])) {
            $defaults['age'] = "checked='checked'";
        }
        foreach ($flavors as $flavor) {
            if (isset($_POST['flavor']) && ($_POST['flavor'] == $flavor)) {
                $defaults['flavor'][$flavor] = "selected='selected'";
            }
        }
    } else {
        print "The form is submitted!";
    }
}
function validate_form()
{
    global $flavors;
    $errors = [];
    if (!(isset($_POST['name']) && (strlen($_POST['name']) > 3))) {
        $errors['name'] = 'Enter a name of at least 3 letters';
    }
    if (isset($_POST['age']) && ($_POST['age'] != '1')) {
        $errors['age'] = 'Invalid age checkbox value.';
    }
    if (isset($_POST['flavor']) && (!in_array($_POST['flavor'], $flavors))) {
        $errors['flavor'] = 'Choose a valid flavor.';
    }

    return $errors;
}

?>

    <form action="<?= htmlentities($_SERVER['SCRIPT_NAME']) ?>" method="post">
        <dl>
            <dt>Your name:</dt>
            <?php if (isset($errors['name'])) { ?>
                <dd class="error"><?= htmlentities($errors['name']) ?></dd>
            <?php } ?>
            <dd>
                <input type="text" name="name" value="<?= htmlentities($defaults['name']) ?>">
            </dd>
            <dt>Are you over 18 years old?</dt>
            <?php if (isset($errors['age'])) { ?>
                <dd class="error"><?= htmlentities($errors['age']) ?></dd>
            <?php } ?>
            <dd><input type="checkbox" name="age" value="1" <?= $defaults['age'] ?> >Yes</dd>
            <dt>Your favorite ice cream flavor:</dt>
            <?php if (isset($errors['flavor'])) { ?>
                <dd class="error"><?= htmlentities($errors['flavor']) ?></dd>
            <?php } ?>
            <dd>
                <select name="flavor">
                    <?php foreach ($flavors as $flavor) { ?>
                        <option <?= isset($defaults['flavor'][$flavor]) ? $defaults['flavor'][$flavor] : " " ?>></option>
                    <?php } ?>
                </select>
            </dd>
        </dl>
        <input type="submit" value="Send Info">
    </form>

    <!-- 在表单中插入一个唯一的ID -->
    <form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>"
          onsubmit="document.getElementById('submit-button').disabled = true;">
        <input type="hidden" name="token" value="<?= md5(uniqid()) ?>">
        <input type="submit" value="Save Data" id="submit-button">
    </form>
<?php
//9.14 防止多次提交表单
//检测表单是否重新提交
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['token'])) {
    $db = new PDO('sqlite:test.db');
    $db->beginTransaction();
    $sth = $db->prepare('select * from forms where token = ?');
    $sth->execute(array($_POST['token']));
    if (count($sth->fetchAll())) {
        print "This form has already been submitted!<br />";
        $db->rollBack();
    } else {
        //其余表单的验证代码放在这里， 验证插入 token 之前的所有内容
        $sth = $db->prepare('insert into forms (token) values (?)');
        $sth->execute(array($_POST['token']));
        $db->commit();
        print "The form is submitted successfully.<br />";
    }
}

/*
 * 使用 SQLite 数据库
class MyDB extends SQLite3
{
    function __construct()
    {
        $this->open('test.db');
    }
}
$db = new MyDB();
if(!$db){
    echo $db->lastErrorMsg();
} else {
    echo "Opened database successfully\n";
}

$sql =<<<EOF
      CREATE TABLE FORMS
      (ID INT PRIMARY KEY,
      NAME           TEXT,
      AGE            INT,
      TOKEN        CHAR(50),
      SALARY         REAL);
EOF;

$ret = $db->exec($sql);
if(!$ret){
    echo $db->lastErrorMsg();
} else {
    echo "Table created successfully\n";
}
$db->close();*/

//9.15 防止全局变量注入
// 不安全的 register_globals 代码
//$db = new PDO('sqlite:test.db');
//$token = $db->quote($_POST['token']);
//$sth = $db->query("select * from forms where token = $token");
//if(1 == $sth->numRows()){
//    $row = $sth->fetchRow(DB_FETCHMODE_OBJECT);
//    $id = $row->id;
//} else {
//    "Prin bad token";
//}
//
//if(!empty($id)){
//    $sth = $db->query("select * from forms where id = $id");
//}

//9.17 使用有多个选项的表单元素
?>
    <input type="checkbox" name="boroughs[]" value="bronx"> The Bronx
    <input type="checkbox" name="boroughs[]" value="brooklyn"> Brooklyn
    <input type="checkbox" name="boroughs[]" value="manhattan"> Manhattan
    <input type="checkbox" name="boroughs[]" value="queens"> Queens
    <input type="checkbox" name="boroughs[]" value="statenisland"> Staten Island

    <input type="checkbox" name="population[NY][NYC]" value="8336697"><br/> <!-- $_POST['population']['NY']['NYC'] -->

<?php
//9.18 根据当前日期创建下拉列表
$options = [];
$when = new DateTime();
// 输出一周的日期
for ($i = 0; $i < 7; ++$i) {
    $options[$when->getTimestamp()] = $when->format("D, F j, Y");
    $when->modify("+1 day");
}

foreach ($options as $value => $label) {
    print "<option value='$value'>$label</option> \n";
}




